import { Injectable } from "@nestjs/common";

import { PrismaService } from "@/core/db/prisma.service";
import BusinessException from "@/core/exception/BusinessException";
import { PageResultVO } from "@/core/vo/page-result.vo";

import { CreateCategoryDto } from "./dto/create-category.dto";
import { QueryCategoryDto } from "./dto/query-category.dto";
import { UpdateCategoryDto } from "./dto/update-category.dto";

@Injectable()
export class CategoryService {
    constructor(private readonly prismaService: PrismaService) {}

    async create(createCategoryDto: CreateCategoryDto) {
        return await this.prismaService.category.create({
            data: createCategoryDto
        });
    }

    async findAll() {
        return await this.prismaService.category.findMany({ where: { isDeleted: false } });
    }

    async findOne(id: number) {
        return await this.prismaService.category.findUnique({
            where: { id, isDeleted: false }
        });
    }

    async findPage(query: QueryCategoryDto) {
        const { current, size, createdAtStart, createdAtEnd, updatedAtStart, updatedAtEnd, name, code } = query;
        const where = {
            name: {
                contains: name
            },
            code,
            isDeleted: false,
            createdAt: {
                gte: createdAtStart,
                lte: createdAtEnd
            },
            updatedAt: {
                gte: updatedAtStart,
                lte: updatedAtEnd
            }
        };
        const [listData, total] = await Promise.all([
            this.prismaService.category.findMany({
                where,
                skip: (current - 1) * size,
                take: size,
                orderBy: {
                    sort: "asc"
                }
            }),
            this.prismaService.category.count({
                where
            })
        ]);

        const pages = Math.ceil(total / size);
        return new PageResultVO(listData, total, pages, current, size);
    }

    async update(id: number, updateCategoryDto: UpdateCategoryDto) {
        let res;
        try {
            res = await this.prismaService.category.update({
                where: {
                    id,
                    isDeleted: false
                },
                data: updateCategoryDto
            });
        } catch (error) {
            throw new BusinessException();
        }
        return res;
    }

    async remove(id: number, softDelete: boolean = true) {
        try {
            if (softDelete) {
                await this.prismaService.category.update({
                    where: {
                        id,
                        isDeleted: false
                    },
                    data: {
                        isDeleted: true,
                        deletedAt: new Date()
                    }
                });
            } else {
                await this.prismaService.category.delete({
                    where: {
                        id,
                        isDeleted: false
                    }
                });
            }
        } catch (error) {
            throw new BusinessException();
        }
    }
}
